/*
 * Created by SharpDevelop.
 * User: ksswyer
 * Date: 7/10/2006
 * Time: 9:52 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

namespace GPSSatellite.Components
{
	/// <summary>
	/// Description of c_SatellitePositioning.
	/// </summary>
	public partial class c_SatellitePositioning
	{
		private const ushort MAXSATS 		= 12;
		private const string CategoryName 	= "Satellite Positioning";
	
		private Image 			mDobleBack = null;
		private string[] 		mSatName = new string[MAXSATS];
		
		private Point			mCenter;
		private int				mOutterRadius;
		private int				mInnerRadius;
		private Sat[]			mSats ;//= new Sat[MAXSATS];
		
		
		#region Component Settings Members
		private bool	mMultiColor = true;
		private bool	mShowLabels = true;
		private ushort  mNumberSats = 0;
		private bool	mShowCompasLetters = true;
		private bool	mShowRings = true;
		#endregion
		
		private struct Sat{
			public string	name;
			public int		azimuth;
			public int 		elevation;
			public bool 	locked;
			public Point	point;
			public bool		draw;
		}
				
		private Color[]	mSatColors = {
			Color.Purple,
			Color.LightSteelBlue,
			Color.ForestGreen,
			Color.Aquamarine,
			Color.Orange,
			Color.Yellow,
			Color.Red,
			Color.Plum,
			Color.CornflowerBlue,
			Color.Blue,
			Color.Olive,
			Color.BurlyWood
		};
		
		public c_SatellitePositioning()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			mCenter.X = (this.ClientRectangle.X+this.ClientRectangle.Width)/2;
			mCenter.Y = (this.ClientRectangle.Y+this.ClientRectangle.Height)/2;
			mOutterRadius = (this.ClientRectangle.Width-8)/2;
			mInnerRadius = mOutterRadius/2;
			
			
			
		}
		
		public void SetSat(int num, int elevation, int azimuth, string text,bool locked,bool draw){
			//TODO: add value checking
			mSats[num-1].azimuth = azimuth;
			mSats[num-1].locked = locked;
			mSats[num-1].name = text;
			mSats[num-1].elevation = elevation;
			
			
			double Re =  mOutterRadius*(90-elevation);
			Re /= 90;
			double rad = (azimuth-90)*(Math.PI/180);
			double x = Math.Cos(rad);
			double y = Math.Sin(rad);
			x = Re*x;
			y = Re*y;
			x += mCenter.X;
			y += mCenter.Y;
			mSats[num-1].point.X = (int)(x);
			mSats[num-1].point.Y = (int)(y);
			mSats[num-1].draw = draw;
			this.Invalidate();
		}
		
		#region Component Settings
		[Category(CategoryName)]
		[Description("Number of satellites to be displayed.")]
		public ushort NumberSats
		{
			get { return mNumberSats; }
			set
			{
				if (mNumberSats> MAXSATS)
					mNumberSats = MAXSATS;
				else{
					mNumberSats = value;
					mSats = new Sat[mNumberSats];
					for (int i=0; i<mNumberSats;i++)
						mSats[i].draw = false;
				}
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Show compas letters for North, South, West and East.")]
		public bool ShowCompasLetters
		{
			get { return mShowCompasLetters; }
			set
			{
				mShowCompasLetters = value;
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Show rings at 0 and 45 degrees to the horizon.")]
		public bool ShowRings
		{
			get { return mShowRings; }
			set
			{
				mShowRings = value;
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Use colored bars = true or single color bars=false.")]
		public bool Multicolored
		{
			get { return mMultiColor; }
			set
			{
				mMultiColor = value;
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Show labels under each bar=true, no labels = false.")]
		public bool ShowLabels
		{
			get { return mShowLabels; }
			set
			{
				mShowLabels = value;
				InvalidateBuffer(true);
			}
		}
	
		#endregion
		#region "  OnSizeChange  "

		protected override void OnSizeChanged(EventArgs e)
		{
			if (!this.IsDisposed)
			{
				if (this.Height < 100)
				{
					this.Height = 100;
				}
				if (this.Height%2 !=0)
					this.Height++;
				
				this.Width = this.Height;
				
				mCenter.X = (this.ClientRectangle.X+this.ClientRectangle.Width)/2;
				mCenter.Y = (this.ClientRectangle.Y+this.ClientRectangle.Height)/2;
				mOutterRadius = (this.ClientRectangle.Width-8)/2;
				mInnerRadius = mOutterRadius/2;
		
				base.OnSizeChanged(e);
				this.InvalidateBuffer(true);
			}

		}

		

		#endregion
		#region Draw Methods
		
		private void InvalidateBuffer()
		{
			InvalidateBuffer(false);
		}

		private void InvalidateBuffer(bool InvalidateControl)
		{
			if (mDobleBack != null)
			{
				mDobleBack.Dispose();
				mDobleBack = null;
			}

			if (InvalidateControl)
			{
				this.Invalidate();
			}
		}
		private void DrawString(Graphics gfx, Rectangle box,string text,Color color)
		{
			SizeF ss = gfx.MeasureString(text, this.Font);

			float left = box.X + (box.Width - ss.Width)/2;
			float top = box.Y + (box.Height - ss.Height)/2;

			
			SolidBrush mTextBrush = new SolidBrush(color);
			gfx.DrawString(text, this.Font, mTextBrush, left, top);
			mTextBrush.Dispose();

		}
		private void DrawSats(Graphics gfx){
			
			for(int i=1; i<mNumberSats; i++){
				if (mSats[i].draw){
					Pen pen;
					Brush brush;
					if (mMultiColor){
						pen = new Pen(Color.Black,1);
						brush = (mSats[i].locked)? new SolidBrush(Color.LightGray):new SolidBrush(mSatColors[i]);
						
					}else{
						pen = new Pen(Color.Black,1);
						brush = new SolidBrush(Color.Gray);
					}
					gfx.DrawPie(pen,
					            mSats[i].point.X-15,
			                	mSats[i].point.Y-15,
			                	25,25,180,90);
					gfx.DrawPie(pen,
					            mSats[i].point.X-10,
			                	mSats[i].point.Y-10,
			                	25,25,0,90);
					gfx.FillPie(brush,
					            mSats[i].point.X-15,
			                	mSats[i].point.Y-15,
			                	25,25,180,90);
					gfx.FillPie(brush,
					            mSats[i].point.X-10,
			                	mSats[i].point.Y-10,
			                	25,25,0,90);
					
					
					gfx.FillEllipse(brush,
			                mSats[i].point.X-10,
			                mSats[i].point.Y-10,
			                20,20);
					gfx.DrawEllipse(pen,
			                mSats[i].point.X-10,
			                mSats[i].point.Y-10,
			                20,20);
					
					if (mShowLabels)
						DrawString(gfx,new Rectangle( 
					        mSats[i].point.X-10,
			                mSats[i].point.Y-9,
			                20,20),mSats[i].name,(mSats[i].locked)?Color.Gray:Color.Black);
				}
			}
		}
		#endregion
		
		#region OnPaint

		protected override void OnPaint(PaintEventArgs e)
		{
			//System.Diagnostics.Debug.WriteLine("Paint " + this.Name + "  Pos: "+this.Position.ToString());
			if (!this.IsDisposed)
			{
				
				if (mDobleBack == null)
				{
					mDobleBack = new Bitmap(this.Width, this.Height);
					Graphics g2 = Graphics.FromImage(mDobleBack);
					if (mShowRings){
						
					
						g2.DrawEllipse(new Pen(Color.Gray,2),
					               mCenter.X-mOutterRadius,
					               mCenter.Y-mOutterRadius,
					               mOutterRadius*2,
					               mOutterRadius*2);
						g2.DrawEllipse(new Pen(Color.Gray,2),
					               mCenter.X-mInnerRadius,
					               mCenter.Y-mInnerRadius,
					               mInnerRadius*2,
					               mInnerRadius*2);
						
					}
					if (mShowCompasLetters){
						DrawString(g2,new Rectangle(mCenter.X-10,mCenter.Y-mOutterRadius,20,20),"N",Color.Black);
						DrawString(g2,new Rectangle(mCenter.X-10,mCenter.Y+mOutterRadius-20,20,20),"S",Color.Black);
						DrawString(g2,new Rectangle(mCenter.X-mOutterRadius,mCenter.Y-10,20,20),"W",Color.Black);
						DrawString(g2,new Rectangle(mCenter.X+mOutterRadius-20,mCenter.Y-10,20,20),"E",Color.Black);
						
					}
					g2.Dispose();
				}

				Image ima = new Bitmap(mDobleBack);

				Graphics gtemp = Graphics.FromImage(ima);
				DrawSats(gtemp);
				
				e.Graphics.DrawImage(ima, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle, GraphicsUnit.Pixel);
				ima.Dispose();
				gtemp.Dispose();

			}

		}
		#endregion
	}
}
